﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Configuration;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Web.UI.WebControls;

using SmartProject.Data;

namespace SmartProject
{
    /// <summary>
    /// A reference class is used with an entity class to provider helper access to
    /// the various attributes that contain multiple values.
    /// </summary>
    /// <remarks>
    /// When creating a table, you may have several foregin keys that simply links to
    /// a name/value pair. A reference table is already defined for this purpose. 
    /// </remarks>
    public abstract class Reference
    {
        private bool _isInitialized;
        private readonly IDataProvider _dataProvider = DataProvider.Instance;
        private string _dataParameterName;
        private string _groupName;
        private Entity _Parent;

        /// <summary>
        /// Gets the name of the group that is used to reference.
        /// </summary>
        public string GroupName
        {
            get { return _groupName; }
        }

        /// <summary>
        /// Gets or sets the data parameter that this reference is associated with.
        /// </summary>
        public string DataParameterName
        {
            get { return _dataParameterName; }
            set { _dataParameterName = value; }
        }

        /// <summary>
        /// Gets or sets the Parent of this reference instance.
        /// </summary>
        public Entity Parent
        {
            get { return _Parent; }
            set { _Parent = value; }
        }

        /// <summary>
        /// Gets the counts of this specific reference from the database.
        /// </summary>
        public int Counts
        {
            get
            {
                _dataProvider.Initialize();
                _dataProvider.Add("@GroupName", _groupName, 50);
                return Entity.GetCounts(_dataProvider, "smartProject_GetReferenceCount");
            }
        }

        public void Populate(DropDownList dropDownList)
        {
            dropDownList.Items.Clear();

            _dataProvider.Initialize();
            _dataProvider.Add("@GroupName", GroupName, 50);

            using (DataTable references = _dataProvider.Find("smartProject_GetReferences"))
            {
                if (references != null)
                {
                    for (int i = 0; i < references.Rows.Count; i++)
                    {
                        string referenceId = references.Rows[i]["ReferenceId"].ToString();
                        string attributeValue = references.Rows[i]["AttributeValue"].ToString();
                        dropDownList.Items.Add(new ListItem(attributeValue, referenceId));
                    }
                    references.Dispose();
                }
            }
        }

        public void Save(DropDownList dropDownList)
        {
            for (int i = 0; i < dropDownList.Items.Count; i++)
            {
                ListItem item = dropDownList.Items[i];
                if (item.Value != "-1")
                {
                    _dataProvider.Initialize();
                    _dataProvider.Add("@ReferenceId", Convert.ToInt32(item.Value));
                    _dataProvider.Add("@AttributeValue", item.Text, 200);
                    _dataProvider.Add("@OrderIndex", i);
                    _dataProvider.Run("smartProject_UpdateReference");
                }
            }
        }

        public void Add(string value)
        {
            Add(value, -1);
        }

        public void Add(string value, int orderIndex)
        {
            _dataProvider.Initialize();
            _dataProvider.Add("@GroupName", GroupName, 50);
            _dataProvider.Add("@AttributeValue", value, 200);
            _dataProvider.Add("@OrderIndex", orderIndex);
            _dataProvider.Run("smartProject_AddReference");
        }

        /// <summary>
        /// You must call this method before using any other methods here.
        /// </summary>
        /// <param name="groupName">Sets the name of the group that is used to reference.</param>
        /// <param name="attributeValues">List of description values in the order of importance.</param>
        protected void Initialize(string groupName, string[] attributeValues)
        {
            // This is to prevent from calling this initialize too many times and only the first time.
            if (!_isInitialized)
            {
                _groupName = groupName;
                if (attributeValues != null && attributeValues.Length > 0)
                {
                    if (this.Counts == 0)
                    {
                        for (int i = 0; i < attributeValues.Length; i++)
                        {
                            Add(attributeValues[i], i);
                        }
                    }
                }
                _isInitialized = true;
            }
        }
       
        public string GetValue(int referenceId)
        {
            _dataProvider.Initialize();
            _dataProvider.Add("@ReferenceId", referenceId);
            return Entity.LoadStringValue(_dataProvider, "smartProject_GetReferenceValue");
        }   

        public int GetId(string value, bool addIfEmpty)
        {
            _dataProvider.Initialize();
            _dataProvider.Add("@GroupName", _groupName, 50);
            _dataProvider.Add("@AttributeValue", value, 200);
            string stringValue = Entity.LoadStringValue(_dataProvider, "smartProject_GetReferenceId");
            if (!String.IsNullOrEmpty(stringValue))
            {
                return Convert.ToInt32(stringValue);
            }
            else
            {
                if (addIfEmpty)
                {
                    Add(value);
                    return Convert.ToInt32(GetId(value, false));
                }
            }
            return -1;
        }
     
        public string Value
        {
            get
            {
                if (_Parent != null)
                {
                    Object obj = _Parent.GetAttributeValue(_dataParameterName);
                    if (obj != null)
                    {
                        return GetValue((int)obj);
                    }
                }
                return String.Empty;
            }
        }
        
        public void Remove(int referenceId)
        {
            _dataProvider.Initialize();
            _dataProvider.Add("@ReferenceId", referenceId);
            _dataProvider.Run("smartProject_RemoveReference");
        }

        public void Update(int referenceId, string value)
        {
            Update(referenceId, value, -1);
        }

        public void Update(int referenceId, string value, int orderIndex)
        {
            _dataProvider.Initialize();
            _dataProvider.Add("@ReferenceId", referenceId);
            _dataProvider.Add("@AttributeValue", value, 200);
            _dataProvider.Add("@OrderIndex", orderIndex);
            _dataProvider.Run("smartProject_UpdateReference");
        }
    }
}
